/**
 * 权限工具：获取用户权限列表
 * @param {string} [type='localStorage'] - 权限存储位置（'localStorage' 或 'sessionStorage'）
 * @returns {string[]} 用户权限列表（默认返回空数组）
 * @description 从本地存储中读取权限列表，自动处理 JSON 解析异常
 */
const getPermission = (type = 'localStorage') => {
  try {
    // 校验存储类型是否合法（只支持 localStorage 或 sessionStorage）
    if (!['localStorage', 'sessionStorage'].includes(type)) {
      console.warn(`权限存储类型 ${type} 不支持，默认使用 localStorage`)
      type = 'localStorage'
    }

    // 根据类型从对应存储中读取权限
    let storagePermission
    if (type === 'localStorage') {
      storagePermission = localStorage.getItem('permissions')
    } else {
      storagePermission = sessionStorage.getItem('permissions')
    }
    if (!storagePermission || storagePermission === 'undefined') {
      return []
    }
    // 解析存储的权限
    const permissions = JSON.parse(storagePermission)

    // 确保返回值是数组
    return Array.isArray(permissions) ? permissions : []
  } catch (error) {
    console.error('获取权限列表失败：', error)
    return [] // 异常时返回空数组，避免后续逻辑报错
  }
}

/**
 * 验证是否拥有指定权限
 * @param {string|string[]} permission - 要验证的权限（单个权限字符串或权限数组）
 * @param {boolean} [strict=false] - 严格模式开关（false：满足一个即可；true：必须全部满足）
 * @param {string} [storageType='localStorage'] - 权限存储位置（可选，默认 localStorage）
 * @returns {boolean} 是否拥有权限（非字符串/数组类型默认返回 false）
 */
const hasPermission = (permission, strict = false, storageType = 'localStorage') => {
  // 1. 获取用户权限列表（支持指定存储位置）
  const userPermissions = getPermission(storageType)

  // 2. 权限列表为空时，直接返回 false
  if (!userPermissions.length) {
    return false
  }

  // 3. 处理单个权限（字符串类型）
  if (typeof permission === 'string') {
    return userPermissions.includes(permission)
  }

  // 4. 处理多个权限（数组类型）
  if (Array.isArray(permission)) {
    // 严格模式：必须包含所有权限
    if (strict) {
      return permission.every(perm => userPermissions.includes(perm))
    }
    // 松散模式（默认）：包含任意一个即可
    return permission.some(perm => userPermissions.includes(perm))
  }

  // 5. 非预期类型（如数字、null 等），返回 false 并警告
  console.warn(`${permission}权限验证参数类型错误，期望 string 或 array，实际为${typeof permission} `)
  return false
}

/**
 * 解析权限指令的绑定值，统一处理不同格式的参数
 * @param {string|string[]|Object} val - 指令绑定值（权限参数）
 * @returns {boolean} 是否拥有权限
 */
const getHas = val => {
  // 1. 处理字符串或数组类型（基础权限验证，默认松散模式）
  if (typeof val === 'string' || Array.isArray(val)) {
    return hasPermission(val)
  }

  // 2. 处理对象类型（支持自定义严格模式和存储位置）
  if (val && typeof val === 'object') {
    // 从对象中提取参数（默认值处理）
    const { permission, strict = false, storageType = 'localStorage' } = val
    // 校验对象中必须包含 permission 字段
    if (permission === undefined) {
      console.warn('权限参数对象缺少 permission 字段')
      return false
    }
    return hasPermission(permission, strict, storageType)
  }

  // 3. 无效参数类型
  console.warn(`${val}权限指令参数格式错误`)
  return false
}

/**
 * 自定义权限指令 v-has
 * 功能：根据用户权限控制元素是否显示（无权限时从 DOM 中移除元素）
 * 使用场景：按钮、菜单等元素的权限控制
 */
export default {
  /**
   * 元素挂载时执行权限校验
   * @param {HTMLElement} el - 指令绑定的 DOM 元素
   * @param {Object} binding - 指令绑定信息（包含 value 等参数）
   */
  mounted(el, binding) {
    // 执行权限校验
    const hasPermission = getHas(binding.value)
    // 无权限时移除元素
    if (!hasPermission && el.parentNode) {
      el.parentNode.removeChild(el)
    }
  },

  /**
   * 元素更新时重新校验权限（支持动态权限变化）
   * @param {HTMLElement} el - 指令绑定的 DOM 元素
   * @param {Object} binding - 指令绑定信息（包含新旧值）
   */
  updated(el, binding) {
    // 只有当绑定值变化时，才重新校验（避免无意义的重复执行）
    if (binding.value !== binding.oldValue) {
      // 先缓存原始父节点和相邻元素（用于后续可能的重新插入）
      const parentNode = el.parentNode || el._parentNode
      const nextSibling = el.nextSibling || el._nextSibling

      // 执行权限校验
      const hasPermission = getHas(binding.value)

      if (hasPermission) {
        // 有权限时，若元素已被移除则重新插入 DOM
        if (parentNode && !el.parentNode) {
          parentNode.insertBefore(el, nextSibling)
        }
      } else {
        // 无权限时移除元素（并缓存父节点信息）
        if (parentNode) {
          el._parentNode = parentNode // 缓存父节点
          el._nextSibling = nextSibling // 缓存相邻元素
          parentNode.removeChild(el)
        }
      }
    }
  }
}
